Skip to content

feat(config): sampler plugin loading via entry points for declarative config#5095

Open
MikeGoldsmith wants to merge 8 commits intoopen-telemetry:mainfrom
MikeGoldsmith:mike/config-sampler-plugin-loading
Open

feat(config): sampler plugin loading via entry points for declarative config#5095
MikeGoldsmith wants to merge 8 commits intoopen-telemetry:mainfrom
MikeGoldsmith:mike/config-sampler-plugin-loading

Conversation

@MikeGoldsmith
Copy link
Copy Markdown
Member

@MikeGoldsmith MikeGoldsmith commented Apr 14, 2026

Description

Extends sampler support in declarative file configuration to handle custom (plugin) samplers, matching the spec's PluginComponentProvider mechanism.

Depends on #5131 (additional_properties support for generated models).

Solution

_create_sampler() checks typed fields on the Sampler dataclass for known types (always_on, always_off, trace_id_ratio_based, parent_based), then falls back to additional_properties for unknown plugin names loaded via load_entry_point("opentelemetry_sampler", name).

_create_parent_based_sampler() uses typed ParentBasedSampler fields for delegate samplers.

Custom sampler example

tracer_provider:
  sampler:
    my_custom_sampler: {}
[project.entry-points."opentelemetry_sampler"]
my_custom_sampler = "my_package:MySamplerClass"

Closes #5071

Extracts a generic `load_entry_point(group, name)` helper into `_common`
so that resource detector, exporter, propagator, and sampler plugin loading
in declarative file config can all use the same entry point lookup pattern
rather than duplicating it.

Refactors `_propagator.py` to use the new util, removing its inline
entry point lookup.

Assisted-by: Claude Sonnet 4.6
Extends _create_sampler() to accept raw dicts (from the YAML path) in
addition to typed dataclasses (from the direct API path). Unknown sampler
names fall back to load_entry_point("opentelemetry_sampler", name),
matching the spec's PluginComponentProvider mechanism and Java SDK
behaviour.

_create_parent_based_sampler() gets the same dict-path treatment so
custom samplers can be used as delegate samplers inside parent_based.

Assisted-by: Claude Sonnet 4.6
Sampler and ParentBasedSampler are changed from @DataClass to
TypeAlias = dict[str, Any] in models.py. The generated dataclass
representation dropped unknown keys, making plugin sampler names
unrecoverable before reaching the factory. The dict type preserves
the raw YAML key, which is the plugin name.

_create_sampler() now has a single code path: extract the single key
as the sampler name, look it up in _SAMPLER_REGISTRY (always_on,
always_off, trace_id_ratio_based, parent_based), and fall back to
load_entry_point("opentelemetry_sampler", name) for unknown names.
This matches the spec's PluginComponentProvider mechanism.

Assisted-by: Claude Sonnet 4.6
Python dataclasses don't enforce types at runtime, so factory functions
can accept raw dicts without changing the generated models. This keeps
models.py identical to the codegen output.

Assisted-by: Claude Opus 4.6 (1M context)
@MikeGoldsmith MikeGoldsmith marked this pull request as draft April 20, 2026 13:52
Use typed SamplerConfig and ParentBasedSamplerConfig with
additional_properties from the @_additional_properties decorator
instead of raw dict iteration. Known sampler types are checked via
typed fields. Unknown plugin names from additional_properties are
loaded via the opentelemetry_sampler entry point group.

Assisted-by: Claude Opus 4.6
@MikeGoldsmith MikeGoldsmith marked this pull request as ready for review April 29, 2026 13:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Ready for review

Development

Successfully merging this pull request may close these issues.

feat(config): generic plugin loading for samplers in declarative config

1 participant